home *** CD-ROM | disk | FTP | other *** search
- (c) Copyright 1991 Commodore-Amiga, Inc. All rights reserved.
- The information contained herein is subject to change without notice,
- and is provided "as is" without warranty of any kind, either expressed
- or implied. The entire risk as to the use of this information is
- assumed by the user.
-
-
-
- Executing External Programs with Release 2.0
-
-
- by Carolyn Scheppner
-
- The 2.0 Amiga operating system provides more flexible methods of
- launching programs from an application. The 2.0 dos.library contains
- a new function, System(), which is more flexible and powerful than the
- 1.3 Execute() function. Improvements to the con-handler, CON:, allow
- programs to create ``auto con'' windows, which are console windows
- that will only appear if input is requested from or output is sent to
- that console. The 2.0 con-handler also provides several other
- enhancements, including Close gadgets for CON: windows and a feature
- which allows a program to use an existing window as its CON: window.
-
-
- The System() Function
-
- The System() function is intended to replace the Execute() function of
- release 1.3. System() spawns a shell process to execute the command
- line which is passed to System() as an argument. The shell parses the
- command-line normally, just like command-lines typed directly into the
- shell's console. If it can, System() will pass the current path and
- directory to the programs it launches.
-
- The System() function can execute external commands either
- synchronously or asynchronously. When System() is used synchronously,
- control returns to the calling program after the external program has
- completed. In this case, System() returns the external program's
- return code, or a -1 if the command could not be found or run. On the
- other hand, when System() initiates a program asynchronously, the
- program is no longer a concern for the caller. The operating system
- will take care of the cleanup. This is extremely useful for an
- application that must start up multiple programs on user demand, such
- as a hot key commodity. By default, System() starts programs
- synchronously. To launch a program asynchronously, use the SYS_Asynch
- tag with the data field set to TRUE.
-
- With the System() call, it is easy to provide programs with specific
- input and output handles. The tags SYS_Input and SYS_Output (defined
- in dos/dostags.h) are used to supply the input and output file
- handles. A program can pass its own input and output handles to a
- synchronously launched program by passing the results of Input() and
- Output(), respectively. Note that with a synchronous System() call,
- the OS will not close these handles when the spawned process exits.
- In the case of an asynchronously launched program, the launching
- program normally must provide new IO handles since the system
- automatically closes these handles when the asynchronous process ends.
- Because AmigaDOS wants separate handles for input and output, System()
- will automatically create an output handle if it's passed a handle for
- SYS_Input and NULL for SYS_Output. This allows a program to open a
- CON: window for input and use it for both input and output, as
- System() will test to see if input is interactive and, if so, will
- attempt to open ``*'' for output to that console. If the input file
- handle is not interactive, System() opens ``*'' on the current console
- task.
-
- Programs launched using System() are not restricted to the built-in,
- or Boot, shell. In the near future, System() will be able to take
- advantage of specially designed shells (the design requirements of
- these special shells have not yet been documented). Two tags,
- SYS_UserShell and SYS_CustomShell, specify which shell System() should
- use to execute the command-line. By using the SYS_UserShell tag with
- a tag value of TRUE, an application tells System() to send a command
- to the user's preferred shell rather that the boot shell (Note that
- the default user shell is the boot shell). If an application opens a
- shell for the user or executes the user's command-lines, it should
- tell System() to use the user shell. If an application requires
- consistent shell behavior, it must not use the user shell because the
- user can change the user shell. Another shell tag, SYS_CustomShell,
- allows an application to choose other shells besides the boot and user
- shells. This tag's data field should contain the custom shell's name
- as it appears in the system resident list.
-
- Although it does offer many features, System() does have some
- limitations. First, because command paths currently only exist in the
- CLI structure, Workbench (non-CLI) processes have no paths.
- Consequently, when a Workbench process calls a program using System(),
- the shell has no path to search for that program (aside from the
- system default search path of C: and the current directory). A second
- limitation of the System() function involves CTRL-C/D/E/F handling.
- When a task opens a CON: window to provide a handle for a
- System()-launched command, that task is the owner of the handle. This
- has two effects. A System()-launched command running in that CON:
- window will only be able to receive CTRL-C/D/E/F signals while it is
- doing input or output to the window (i.e. when it has a pending read
- or write). If the task that owns the handle is still around, it
- receives CTRL-C/D/E/F signals whenever those keys are pressed in the
- CON: window.
-
-
- The 2.0 Con-handler
-
- The 2.0 con-handler (CON:) has many new enhancements that allow
- programs to further customize their console windows. An application
- requests these new features by appending keywords to the end of the
- CON: specification string for Open(). These keywords may appear in
- any order after the title string in the CON: specification.
-
- These new keywords are:
-
- AUTO Don't open CON: window until/unless input or
- output occurs
- CLOSE Put a close gadget on the CON: window
- WAIT Hold off Close until user clicks Close or types CTRL-\
- WINDOW 0xaddr Use specified window (may be on a custom screen)
- SCREEN name Open on specified public screen
-
- The additional CON: keywords BACKDROP, NODRAG, NOBORDER, NOSIZE,
- SIMPLE, and SMART, allow control of other attributes of a CON: window.
-
- An AUTO/CLOSE/WAIT CON: window is perfect for 2.0-specific C startup
- code and for asynchronous System() startup of arbitrary commands.
- Because of the ``auto con'' feature (AUTO), the system will never open
- the CON: window of a program that doesn't do any stdio (example:
- Calculator). If a command does stdio input or output, the window will
- not open until stdio occurs. If the window opens, the wait feature
- (WAIT) causes the window to stay open until the user types CTRL-\ (end
- of file) or clicks the Close gadget. The CLOSE keyword tells the
- con-handler to put a close gadget on the CON: window.
-
- Example: ``CON:/0/0/640/200/My Title/AUTO/CLOSE/WAIT''
-
- The SCREEN keyword along with a public screen name allows an
- application to open a CON: window on that public screen. Alternately,
- an application can use the WINDOW keyword to attach a console to an
- already open Intuition window. The hex address of the Intuition
- window must follow the WINDOW keyword. This makes it possible for
- System()-launched programs to do their stdio in a window on a custom
- screen.
-
- The example code, SystemTest.c, provides two simple subroutines for
- executing external commands, and demonstrates the following 2.0
- features:
-
- o Synchronous System() command execution using the calling
- program's Input()/Output().
- o Synchronous System() command execution in a custom screen window.
- o Asynchronous System() command startup with an AUTO/CLOSE/WAIT window.
- o OpenScreenTags and OpenWindowTags for a 2.0 New Look window.
-
-
-
-
- ;/* SystemTest.c - Execute me to compile me with Lattice 5.04
- ; Demonstration of System(), AUTO CON, and custom screen CON
- LC -b1 -cfistq -v -y -j73 SystemTest.c
- Blink FROM LIB:c.o,SystemTest.o TO SystemTest LIBRARY LIB:LC.lib,LIB:Amiga.lib
- quit
- */
-
- #include <exec/types.h>
- #include <exec/libraries.h>
- #include <dos/dos.h>
- #include <dos/dostags.h>
- #include <intuition/intuition.h>
- #include <graphics/displayinfo.h>
-
- #ifdef LATTICE
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/intuition_protos.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */
- int chkabort(void) { return(0); } /* really */
- #endif
-
- /* our function error codes */
- #define SYSTEMFAIL (-1L)
- #define WINDOWFAIL (-2L)
-
- /* function prototypes */
- LONG beginCommand(UBYTE *command);
- LONG doCommand(UBYTE *command, BPTR other);
- VOID checkResult(UBYTE *command, LONG result);
-
-
- /* Formatted version string for the 2.0 VERSION command */
- UBYTE *vers = "\0$VER: SystemTest 36.10";
-
- struct Library *IntuitionBase;
-
-
- struct Screen *OpenScreenTags(struct NewScreen *,ULONG tags, ...);
- struct Window *OpenWindowTags(struct NewWindow *,ULONG tags, ...);
-
-
- void main(int argc, char **argv)
- {
- extern struct Library *DOSBase;
- struct Screen *scr = NULL;
- struct Window *win = NULL;
- ULONG penspecterm = ~0;
- LONG result;
- BPTR file;
- UBYTE *command;
- UBYTE buf[128];
-
- if(DOSBase->lib_Version < 36)
- {
- printf("This example requires dos.library V36 or higher\n");
- exit(RETURN_FAIL);
- }
- if(!(IntuitionBase = OpenLibrary("intuition.library",36)))
- {
- printf("This example requires intuition.library V36 or higher\n");
- exit(RETURN_FAIL);
- }
-
- /* SYNCHRONOUS SYSTEM() WITH OUR INPUT/OUTPUT
- */
- printf("\n*** SystemTest: Synchronous System call 'dir libs:':\n");
- command = "dir libs:";
- result = doCommand(command,NULL);
- checkResult(command,result);
- printf("\n*** SystemTest: Synchronous System call of nonexistant command:\n");
- command = "badcommand";
- result = doCommand(command,NULL);
- checkResult(command,result);
-
- printf("\n*** SystemTest: Synchronous System call 'ask \"...Answer y now\"':\n");
- command =
- "ask \"Ready for CON: on a Custom Screen? Answer y now (should return 5):\"";
- result = doCommand(command,NULL);
- checkResult(command,result);
-
- /* SYNCHRONOUS SYSTEM() WITH CON: IN A CUSTOM SCREEN AND WINDOW
- */
- if(scr = OpenScreenTags(NULL,
- SA_Width, 640,
- SA_Height, 200,
- SA_Depth, 3,
- SA_DisplayID, HIRES_KEY,
- SA_Pens, &penspecterm, /* Give us New Look */
- TAG_DONE))
- {
- if(win = OpenWindowTags(NULL,
- WA_CustomScreen, scr,
- WA_Flags, WINDOWDRAG|WINDOWCLOSE|ACTIVATE,
- WA_IDCMP, CLOSEWINDOW,
- WA_Top, 20,
- WA_Height, scr->Height - 20,
- WA_Title, "Custom Window",
- WA_ScreenTitle, "Custom Screen",
- TAG_DONE))
- {
- sprintf(buf,"CON://///WINDOW0x%lx", win); /* adds window pointer */
- if(file = Open(buf, MODE_OLDFILE))
- {
- command = "echo \"CLI commands on a custom screen!\"";
- result = doCommand(command,file);
- command = "dir libs:";
- result = doCommand(command,file);
- command = "echo \"( Click CLOSE gadget, or type CTRL-C )\"";
- result = doCommand(command,file);
- Wait(1 << win->UserPort->mp_SigBit | SIGBREAKF_CTRL_C);
- Close(file); /* Closes the window too */
- }
- else CloseWindow(win);
- }
- CloseScreen(scr);
- }
-
- printf("\n*** SystemTest: Synchronous System call 'ask \"...Answer y now\"':\n");
- command = "ask \"Ready for Asynchronous demo? Answer y now (should return 5):\"";
- result = doCommand(command,NULL);
- checkResult(command,result);
-
-
- /* ASYNCHRONOUS SYSTEM() WITH ON-DEMAND AUTO/WAIT CON:
- */
- printf("\n*** SystemTest: Asynchronous startup of 'Sys:Utilities/Clock':\n");
- command = "SYS:Utilities/Clock";
- result = beginCommand(command);
- checkResult(command,result);
-
- printf("\n*** SystemTest: Asynchronous startup of 'avail':\n");
- command = "avail";
- result = beginCommand(command);
- checkResult(command,result);
-
- printf("\nSystemTest exiting. Close Clock and Autocon window when you wish.\n");
-
- CloseLibrary(IntuitionBase);
- exit(RETURN_OK);
- }
-
-
-
-
-
- /*
- * Synchronous external command (wait for return)
- * Uses your Input/Output unless you supply other handle
- * Result will be return code of the command, unless the System() call
- * itself fails, in which case the result will be -1
- */
- LONG doCommand(UBYTE *command, BPTR other)
- {
- struct TagItem stags[4];
-
- stags[0].ti_Tag = SYS_Input;
- stags[0].ti_Data = other ? other : Input();
- stags[1].ti_Tag = SYS_Output;
- stags[1].ti_Data = other ? NULL: Output();
- stags[3].ti_Tag = TAG_DONE;
- return(System(command, stags));
- }
-
-
-
-
- /*
- * Asynchronous external command started with its own autocon Input/Output
- * This routine shows use of the SYS_UserShell tag as well.
- * Result will only reflect whether System() call itself succeeded.
- * If System() call fails, result will be -1L
- * We are using -2L as result if our Open of CON: fails
- */
- UBYTE *autocon="CON:0/40/640/150/Auto CON Window Opens if Needed/auto/close/wait";
- LONG beginCommand(UBYTE *command)
- {
- struct TagItem stags[5];
- BPTR file;
-
- if(file = Open(autocon, MODE_OLDFILE))
- {
- stags[0].ti_Tag = SYS_Input;
- stags[0].ti_Data = file;
- stags[1].ti_Tag = SYS_Output;
- stags[1].ti_Data = NULL;
- stags[2].ti_Tag = SYS_Asynch;
- stags[2].ti_Data = TRUE;
- stags[3].ti_Tag = SYS_UserShell;
- stags[3].ti_Data = TRUE;
- stags[4].ti_Tag = TAG_DONE;
- return(System(command, stags));
- }
- else return(WINDOWFAIL);
- }
-
-
-
-
-
- /*
- * Demo routine outputs result of System
- */
- VOID checkResult(UBYTE *command, LONG result)
- {
- if(result == SYSTEMFAIL)
- printf("*** SystemTest: could not start process for command\n");
- else if(result == WINDOWFAIL)
- printf("*** SystemTest: can't open con: for command\n");
- else
- printf("*** SystemTest: command (if synchronous) returned %ld\n",result);
- }
-
-
-
-
-
-
- /*
- * Stack based stubs for opening screen, window
- */
- struct Screen *OpenScreenTags(ns, tags)
- struct NewScreen *ns;
- ULONG tags;
- {
- return (OpenScreenTagList(ns, (struct TagItem *)&tags));
- }
-
- struct Window *OpenWindowTags(nw, tags)
- struct NewWindow *nw;
- ULONG tags;
- {
- return (OpenWindowTagList(nw, (struct TagItem *)&tags));
- }
-
-
-